<template>
  <div
    v-infinite-scroll="loadComments"
    :infinite-scroll-disabled="loadDisabled"
    class="m-y-20px"
  >
    <!-- label -->
    <div class="leading-28px flex gap20px">
      <div>
        <span class="text-24px c-#18191c m-r-6px">评论</span>
        <span class="text-14px c-#9499a0">{{ videoInfo?.commentCount }}</span>
      </div>
      <div class="flex items-center gap10px c-#9499a0">
        <span class="cursor-pointer hover:c-#00aeec" @click="sortComments(1)">
          最热
        </span>
        <div class="h-15px b-l b-l-solid b-l-#e3e5e7"></div>
        <span class="cursor-pointer hover:c-#00aeec" @click="sortComments(2)">
          最新
        </span>
      </div>
    </div>

    <!-- input -->
    <CommentsInput
      :contentId="props.contentId"
      :contentType="props.contentType"
      :disabled="props.disabled"
      @getCommentList="getCommentList"
    ></CommentsInput>

    <!-- 评论列表数据 -->
    <div>
      <div
        v-for="(item, index) in commentList"
        class="flex gap10px m-y-10px"
        :key="item.id"
      >
        <div
          :style="{ backgroundImage: `url(${item.createAvatar})` }"
          class="w-48px h-48px b-rd-full pos-relative bg-cover bg-center cursor-pointer"
          :ref="(el) => setUserInfoRef(item.id, el)"
          @mouseenter="showUserInfo(true, item.id)"
          @mouseleave="showUserInfo(false, item.id)"
          @click.stop="router.push('/' + item.createBy)"
        >
          <UserProfileCard
            :item="item"
            :direction="popupDirections[item.id]"
            :offset="48"
            v-if="
              userInfoVisible[item.id] &&
              userStore.userInfo.id !== item.createBy
            "
            @mouseenter="showUserInfo(true, item.id)"
            @mouseleave="showUserInfo(false, item.id)"
          ></UserProfileCard>
        </div>

        <div flex-1>
          <div class="leading-30px m-b-4px">
            <span
              :ref="(el) => setUserInfoRef(item.id + item.createByName, el)"
              @mouseenter="showUserInfo(true, item.id + item.createByName)"
              @mouseleave="showUserInfo(false, item.id + item.createByName)"
              class="text-14px c-#61666d pos-relative cursor-pointer"
              @click.stop="router.push('/' + item.createBy)"
              >{{ item.createByName }}
              <UserProfileCard
                :item="item"
                :direction="popupDirections[item.id + item.createByName]"
                :offset="20"
                v-if="
                  userInfoVisible[item.id + item.createByName] &&
                  userStore.userInfo.id !== item.createBy
                "
                @mouseenter="showUserInfo(true, item.id + item.createByName)"
                @mouseleave="showUserInfo(false, item.id + item.createByName)"
              ></UserProfileCard>
            </span>

            <span
              class="c-sky-500 text-20px m-l-5px v-mid"
              :class="`iconfont icon-icon-lv${item.createUserLevel}`"
            ></span>
          </div>
          <div class="c-#18191c text-15px">
            {{ item.commentText }}
          </div>
          <div class="c-#9499a0 text-13px m-t-4px leading-30px">
            <span>{{ item.createTime }}</span>
            <span
              @click="likeCount(item.id as string, 0)"
              class="cursor-pointer hover:c-#00aeec"
              :class="{ 'c-#00aeec': item.isLiked === 0 }"
            >
              <span class="iconfont icon-zan m-l-20px m-r-5px"></span>
              <span>{{ item.likeCount }}</span>
            </span>
            <span
              @click="likeCount(item.id as string, 1)"
              class="iconfont icon-zanno m-x-15px v-btm cursor-pointer hover:c-#00aeec"
              :class="{ 'c-#00aeec': item.isLiked === 1 }"
            ></span>
            <span
              @click="
                commentInputSelIndex === item.id
                  ? (commentInputSelIndex = null)
                  : (commentInputSelIndex = item.id)
              "
              class="cursor-pointer hover:c-#00aeec"
            >
              回复
            </span>
          </div>
          <div
            v-if="item.replyCount > 0 && !item.children"
            class="c-#9499a0 text-13px"
          >
            共{{ item.replyCount }}条回复，
            <span
              @click="
                getCommentList(item.id);
                childCommentFromSearch.pageNum = 1;
              "
              class="cursor-pointer hover:c-#00aeec"
            >
              点击查看
            </span>
          </div>

          <CommentsInput
            v-if="commentInputSelIndex === item.id"
            :contentId="props.contentId"
            :contentType="props.contentType"
            :inputPlaceholder="`回复 @${item.createByName}：`"
            :comments="item"
            :rootId="item.id"
            @getCommentList="getCommentList"
          ></CommentsInput>

          <!-- 子列表 -->
          <div
            v-for="(reply, index) in item.children"
            class="flex gap10px m-y-10px"
            :key="reply.id"
            v-if="item.children"
          >
            <div
              :style="{ backgroundImage: `url(${reply.createAvatar})` }"
              class="w-24px h-24px b-rd-full m-t-5px pos-relative bg-cover bg-center cursor-pointer"
              :ref="(el) => setUserInfoRef(reply.id, el)"
              @mouseenter="showUserInfo(true, reply.id)"
              @mouseleave="showUserInfo(false, reply.id)"
              @click.stop="router.push('/' + reply.createBy)"
            >
              <UserProfileCard
                :item="reply"
                :direction="popupDirections[reply.id]"
                :offset="24"
                v-if="
                  userInfoVisible[reply.id] &&
                  userStore.userInfo.id !== reply.createBy
                "
                @mouseenter="showUserInfo(true, reply.id)"
                @mouseleave="showUserInfo(false, reply.id)"
              ></UserProfileCard>
            </div>

            <div flex-1>
              <div class="leading-30px m-b-4px">
                <span
                  :ref="
                    (el) => setUserInfoRef(reply.id + reply.createByName, el)
                  "
                  @mouseenter="
                    showUserInfo(true, reply.id + reply.createByName)
                  "
                  @mouseleave="
                    showUserInfo(false, reply.id + reply.createByName)
                  "
                  class="text-14px c-#61666d pos-relative cursor-pointer"
                  @click.stop="router.push('/' + reply.createBy)"
                >
                  {{ reply.createByName }}
                  <UserProfileCard
                    :item="reply"
                    :direction="popupDirections[reply.id + reply.createByName]"
                    :offset="20"
                    v-if="
                      userInfoVisible[reply.id + reply.createByName] &&
                      userStore.userInfo.id !== reply.createBy
                    "
                    @mouseenter="
                      showUserInfo(true, reply.id + reply.createByName)
                    "
                    @mouseleave="
                      showUserInfo(false, reply.id + reply.createByName)
                    "
                  ></UserProfileCard>
                </span>
                <span
                  class="c-sky-500 text-20px m-l-5px v-mid"
                  :class="`iconfont icon-icon-lv${reply.createUserLevel}`"
                ></span>
                <span
                  v-if="
                    item.createBy !== reply.replyToUserId &&
                    item.id !== reply.parentId
                  "
                  class="m-l-10px text-15px"
                >
                  回复
                  <span
                    :ref="
                      (el) => setUserInfoRef(reply.id + reply.replyUserName, el)
                    "
                    @mouseenter="
                      showUserInfo(true, reply.id + reply.replyUserName)
                    "
                    @mouseleave="
                      showUserInfo(false, reply.id + reply.replyUserName)
                    "
                    class="c-#008ac5 m-r-2px cursor-pointer pos-relative"
                    @click.stop="router.push('/' + reply.replyToUserId)"
                  >
                    @{{ reply.replyUserName }}
                    <UserProfileCard
                      :item="{
                        createAvatar: reply.replyUserAvatar,
                        createByName: reply.replyUserName,
                        createUserLevel: reply.replyUserLevel,
                        createFollowNum: reply.replyFollowNum,
                        createFansNum: reply.replyFansNum,
                        createUserSignature: reply.replyUserSignature,
                        createBy: reply.replyToUserId,
                      }"
                      :direction="
                        popupDirections[reply.id + reply.replyUserName]
                      "
                      :offset="20"
                      v-if="
                        userInfoVisible[reply.id + reply.replyUserName] &&
                        userStore.userInfo.id.toString() !==
                          String(reply.replyToUserId)
                      "
                      @mouseenter="
                        showUserInfo(true, reply.id + reply.replyUserName)
                      "
                      @mouseleave="
                        showUserInfo(false, reply.id + reply.replyUserName)
                      "
                    ></UserProfileCard>
                  </span>
                  :
                </span>
                <span class="c-#18191c m-l-10px">{{ reply.commentText }}</span>
              </div>
              <div class="c-#9499a0 text-13px m-t-4px leading-30px">
                <span>{{ reply.createTime }}</span>
                <span
                  @click="likeCount(reply.id as string, 0)"
                  class="cursor-pointer hover:c-#00aeec"
                  :class="{ 'c-#00aeec': reply.isLiked === 0 }"
                >
                  <span class="iconfont icon-zan m-l-20px m-r-5px"></span>
                  <span>{{ reply.likeCount }}</span>
                </span>
                <span
                  @click="likeCount(reply.id as string, 1)"
                  class="iconfont icon-zanno m-x-15px v-btm cursor-pointer hover:c-#00aeec"
                  :class="{ 'c-#00aeec': reply.isLiked === 1 }"
                ></span>
                <span
                  @click="
                    commentInputSelIndex === reply.id
                      ? (commentInputSelIndex = null)
                      : (commentInputSelIndex = reply.id)
                  "
                  class="cursor-pointer hover:c-#00aeec"
                >
                  回复
                </span>
              </div>

              <CommentsInput
                v-if="commentInputSelIndex === reply.id"
                :contentId="props.contentId"
                :contentType="props.contentType"
                :inputPlaceholder="`回复 @${reply.createByName}：`"
                :comments="reply"
                :rootId="item.id"
                @getCommentList="getCommentList"
              ></CommentsInput>
            </div>
          </div>

          <!-- hide-on-single-page -->
          <div v-if="item.children" class="flex gap10px">
            <el-pagination
              v-model:current-page="childCommentFromSearch.pageNum"
              :page-size="childCommentFromSearch.pageSize"
              layout="total, prev, pager, next"
              :total="childTotal"
              size="small"
              @current-change="getCommentList(item.id)"
            />
            <span
              class="c-#606266 text-12px leading-24px hover:c-#00aeec cursor-pointer"
              @click="item.children = null"
            >
              收起
            </span>
          </div>
        </div>
      </div>

      <!-- 交互体验 -->
      <el-skeleton
        v-if="loading"
        style="--el-skeleton-circle-size: 48px"
        animated
      >
        <template #template>
          <div flex gap20px>
            <el-skeleton-item variant="circle" />
            <el-skeleton :rows="2" />
          </div>
        </template>
      </el-skeleton>
    </div>
  </div>
</template>

<script setup lang="ts">
import { onMounted, ref, nextTick } from "vue";
import type {
  ContentCommentQuery,
  ContentCommentVO,
} from "@/api/contentComment/types";
import {
  likeCountApi,
  listContentComment as listContentCommentApi,
} from "@/api/contentComment";
import CommentsInput from "@/components/CommentsInput.vue";
import UserProfileCard from "./UserProfileCard.vue";
import { useUserStore } from "@/store/userStore";
import { getVideo } from "@/api/video";
import type { VideoVO } from "@/api/video/types";
import router from "@/router";

const userStore = useUserStore();

const videoInfo = ref<VideoVO>();

const props = defineProps({
  contentId: {
    // 内容id
    required: true,
    type: [String, Number],
  },
  contentType: {
    // 内容类型 1-视频，2-音频，3-文章
    required: true,
    type: [Number],
  },
  disabled: {
    // 是否禁用评论
    required: true,
    type: Boolean,
  },
});

// 评论输入框选择下标
const commentInputSelIndex = ref();

// 评论数据
const commentList = ref<ContentCommentVO[]>([]);

// 用户信息显示状态
const userInfoVisible = ref<Record<string, boolean>>({});
const popupDirections = ref<Record<string, "up" | "down">>({});
const userInfoRefs = new Map<string | number, HTMLElement | null>();

// 评论搜索条件
const commentFromSearch = ref<ContentCommentQuery>({
  contentId: props.contentId,
  contentType: props.contentType,
  pageSize: 10,
  pageNum: 1,
  parentId: 0,
});

// 子评论搜索条件
const childCommentFromSearch = ref<ContentCommentQuery>({
  contentId: props.contentId,
  contentType: props.contentType,
  pageSize: 10,
  pageNum: 1,
  rootId: 0,
});

// 子评论分页总数
const childTotal = ref(0);
const loading = ref(false);
// 是否禁用无限滚动加载
const loadDisabled = ref(false);

// 排序评论
const sortComments = (type: number) => {
  if (type === 1) {
    commentFromSearch.value.isAsc = "desc";
    commentFromSearch.value.orderByColumn = "likeCount";
    childCommentFromSearch.value.isAsc = "desc";
    childCommentFromSearch.value.orderByColumn = "likeCount";
  } else if (type === 2) {
    commentFromSearch.value.isAsc = "desc";
    commentFromSearch.value.orderByColumn = "createTime";
    childCommentFromSearch.value.isAsc = "desc";
    childCommentFromSearch.value.orderByColumn = "createTime";
  }
  commentFromSearch.value.pageNum = 1; // 重置页码
  getCommentList();
};

// 显示或隐藏用户信息
function setUserInfoRef(id: string | number, el) {
  userInfoRefs.set(id, el);
}

// 显示用户信息卡片
function showUserInfo(flag: boolean, id: string | number) {
  userInfoVisible.value[id] = flag;

  if (flag) {
    nextTick(() => {
      const el = userInfoRefs.get(id);
      if (el) {
        const rect = el.getBoundingClientRect();
        popupDirections.value[id] = rect.top < 200 ? "down" : "up";
      }
    });
  }
}

// 获取视频详细信息
const getVideoInfo = async () => {
  let videoInfoRes = await getVideo(props.contentId as string);
  videoInfo.value = videoInfoRes.data;
};

// 获取评论数据
const getCommentList = async (id?: string | number, isRefreshList = false) => {
  if (isRefreshList) {
    await getVideoInfo();
  }

  if (id) {
    childCommentFromSearch.value.rootId = id;
  }

  let res = await listContentCommentApi(
    id ? childCommentFromSearch.value : commentFromSearch.value
  );

  if (id) {
    commentList.value.forEach((item) => {
      if (item.id === id) {
        item.children = res.rows || [];
        childTotal.value = res.total;
      }
    });
  } else {
    commentList.value = res.rows;
  }
};

// 无限滚动加载评论
const loadComments = async () => {
  loading.value = true;
  commentFromSearch.value.pageNum += 1;
  const res = await listContentCommentApi(commentFromSearch.value);
  if (res.rows.length > 0) {
    commentList.value.push(...res.rows);
  } else {
    loadDisabled.value = true; // 没有更多数据了，禁用无限滚动加载
    commentFromSearch.value.pageNum = Math.max(
      1,
      commentFromSearch.value.pageNum - 1
    );
  }
  loading.value = false;
};

// type 0 点赞 1 取消点赞
const likeCount = async (id: string, type: number) => {
  await likeCountApi({
    id: id,
    type: type,
  });
  getCommentList();
};

onMounted(async () => {
  // 获取评论数据
  sortComments(1); // 默认按最热排序
  await getVideoInfo();
});
</script>

<style scoped></style>
